package jvm.reference;

import javax.sound.midi.Track;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;

/**
 * <P> @Author: ideaAdmin
 * <P> TODO: Class
 * <P> TODO: 虚引用
 * <P> Date: 2022/3/22:19:46
 * <P> Description:
 */

public class PhantomReferenceTest {
    public static PhantomReferenceTest phantom;

    //设置引用队列
    public static ReferenceQueue<PhantomReferenceTest> queue = null;

    public static class CheckRefQueue extends Thread{
        @Override
        public void run() {
            while (true){
              if(queue != null){
                  PhantomReference phantomReference = null;

                  try {
                      phantomReference  = (PhantomReference) queue.remove();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }

                  if(phantomReference == null){
                      System.out.println("追踪垃圾回收线程，phantomReference实例被回收");
                  }

              }
            }
        }
    }

    public static void main(String[] args) {
        Thread thread = new CheckRefQueue();
        thread.setDaemon(true);
        thread.start();

        phantom = new PhantomReferenceTest();
        queue = new ReferenceQueue<PhantomReferenceTest>();
        //构造 PhantomReferenceTest 的虚引用 并指定了引用队列
        PhantomReference phantomReference = new PhantomReference<>(phantom,queue);

        try {
            //试图获取虚引用中的对象
            System.out.println("试图获得phantomReference中对象"+phantomReference.get());

            //去掉强引用
            phantom = null;

            //调用GC 由于对象可复活  所以GC无法回收该对象
            System.gc();
            System.out.println("第一次GC");
            Thread.sleep(1000);

            if(phantom ==null){
                System.out.println("phantom is null");
            }else {
                System.out.println("phantom is not null");
            }

            phantom = null;
            System.gc();
            System.out.println("第二次GC");
            
            Thread.sleep(1000);

            if(phantom ==null){
                System.out.println("phantom is null");
            }else {
                System.out.println("phantom is not null");
            }
        }catch (InterruptedException e){

        }
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("PhantomReferenceTest.finalize");
        phantom = this;
    }
}
